package genCodeUtil.util;

import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 〈一句话功能简述〉<br>
 * 验证
 *
 * @author wp
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
public class ValidateUtils {

    public ValidateUtils() {
    }

    /**
     * 判断数是否在范围内，
     *
     * @param param 要检查的参数
     * @param min   最小值
     * @param max   最大值
     * @return 如果参数在[min, max]范围则返回true，否则false
     */
    public static <T extends Comparable<T>> boolean isInRange(T param, T min, T max) {
        if (param == null)
            return false;
        return min.compareTo(param) <= 0 && max.compareTo(param) >= 0;
    }

    /**
     * 检查参数是否在指定数组中
     *
     * @param param    要进行检查的参数
     * @param valueSet 值域
     * @return 如果值域包含值则返回true，否则false
     */
    public static boolean isIn(Object param, Object... valueSet) {
        for (Object t : valueSet) {
            if (t.equals(param))
                return true;
        }
        return false;
    }

    /**
     * 检查参数是否在指定数组中
     *
     * @param param    要进行检查的参数
     * @param valueSet 值域
     * @return 如果值域包含值则返回true，否则false
     */
    public static boolean isIn(Object param, List<Object> valueSet) {
        for (Object t : valueSet) {
            if (t.equals(param))
                return true;
        }
        return false;
    }

    /**
     * 判断一个字符串数字是否在范围内
     *
     * @param param 要检查的参数
     * @param min   最小值
     * @param max   最大值
     */
    public static boolean isInRange(String param, double min, double max) {
        if (param == null)
            return false;
        try {
            Double num = new Double(param);
            return num >= min && num <= max;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    /**
     * 验证是否为int类型
     *
     * @param arg
     * @return
     */
    public static boolean isInt(String arg) {
        if (arg == null)
            return false;
        try {
            Integer.valueOf(arg);
        } catch (NumberFormatException e) {
            return false;
        }
        return true;
    }

    /**
     * 验证是否为int类型,并且在一个范围里面
     *
     * @param arg
     * @param min
     * @param max
     * @return
     */
    public static boolean isIntRange(String arg, int min, int max) {
        if (arg == null)
            return false;
        try {
            int param = Integer.valueOf(arg.trim());
            if (param >= min && param <= max) {
                return true;
            }
        } catch (NumberFormatException e) {
            return false;
        }
        return false;
    }

    /**
     * 验证是否为float类型
     *
     * @param arg
     * @return
     */
    public static boolean isFloat(String arg) {
        if (arg == null)
            return false;
        try {
            Float.valueOf(arg);
        } catch (NumberFormatException e) {
            return false;
        }
        return true;
    }

    public static boolean isLong(String arg) {
        if (arg == null)
            return false;
        try {
            Long.valueOf(arg);
        } catch (NumberFormatException e) {
            return false;
        }
        return true;
    }

    public static boolean isDouble(String arg) {
        if (arg == null)
            return false;
        try {
            new BigDecimal(arg);
        } catch (NumberFormatException e) {
            return false;
        }
        return true;
    }

    public static boolean isBetweenBigDecimal(String arg, double min, double max) {
        if (arg == null)
            return false;
        try {
            Double.valueOf(arg);
        } catch (NumberFormatException e) {
            return false;
        }
        return new BigDecimal(arg).compareTo(new BigDecimal(min + "")) >= 0
                && new BigDecimal(arg).compareTo(new BigDecimal(max + "")) <= 0;
    }

    public static boolean isDateTime(String arg) {
        if (arg == null)
            return false;
        try {
            return toDateTime(arg) != null;
        } catch (IllegalArgumentException e) {

        }
        return false;
    }

    private static Timestamp toDateTime(String arg) {
        Locale locale;
        Timestamp ret;
        locale = Locale.ENGLISH;
        if (arg == null || "".equals(arg))
            return null;
        ret = null;
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", locale);
            ret = new Timestamp(sdf.parse(arg).getTime());
            return ret;
        } catch (ParseException e) {

        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm", locale);
            ret = new Timestamp(sdf.parse(arg).getTime());
            return ret;
        } catch (ParseException e1) {

        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", locale);
            ret = new Timestamp(sdf.parse(arg).getTime());
            return ret;
        } catch (ParseException e2) {

        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd", locale);
            ret = new Timestamp(sdf.parse(arg).getTime());
            return ret;
        } catch (ParseException e2) {

        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM", locale);
            ret = new Timestamp(sdf.parse(arg).getTime());
            return ret;
        } catch (ParseException e3) {

        }

        try {
            SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", locale);
            return new Timestamp(sdf.parse(arg).getTime());
        } catch (Exception e4) {

        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy.M", locale);
            ret = new Timestamp(sdf.parse(arg).getTime());
            return ret;
        } catch (ParseException e5) {

        }
        throw new IllegalArgumentException("参数非法:" + arg);
    }

    public static boolean isNull(String value) {
        return value == null || "".equals(value.trim())
                || "null".equals(value.trim());
    }

    public static boolean isNull(Object value) {
        if (value == null)
            return true;
        if (value instanceof String)
            return isNull((String) value);
        else
            return false;
    }

    public static boolean isNull(Object... values) {
        if (values == null){
            return true;
        }
        for(Object value:values){
            if (value == null){
                return true;
            }
            if (value instanceof String){
                String v = (String) value;
                if(v == null || "".equals(v.trim())
                        || "null".equals(v.trim())){
                    return true;
                }
            }
        }
        return false;
    }




    public static boolean isNotNull(String value) {
        return !isNull(value);
    }

    public static boolean isNotNull(Object value) {
        return !isNull(value);
    }

    public static void notNull(Object object, String message) {
        if (object == null)
            throw new IllegalArgumentException(message);
        else
            return;
    }

    public static void notNull(Object object) {
        notNull(object,
                "[Assertion failed] - this argument is required; it must not null");
    }

    /**
     * 字符串长度不符合规定 为空，为null，为空串 或长度超出都会返回true
     * @author zhaoXinXing
     * @date 2019/4/30
     * @param value 待验证字符串
     * @param length 限制长度
     */
    public static boolean exceedLength(String value, int length) {
        return value == null || "".equals(value.trim())
                || "null".equals(value.trim()) || value.length() > length;
    }

    public static boolean equalLength(String value, int length) {
        return value == null || "".equals(value.trim())
                || "null".equals(value.trim()) || value.length() != length;
    }

    public static boolean lessLength(String value, int length) {
        return value == null || "".equals(value.trim())
                || "null".equals(value.trim()) || value.length() < length;
    }

    /**
     * 数字或大写字母(不包括I,O,Z,S,V)组成
     *
     * @return
     */
    public static boolean isNumbersAndUppercaseLetters(String value) {

        return Pattern.matches("^[A-Z0-9]+$", value) &&
                !Pattern.matches("^I|O|Z|S|V$", value);
    }

    public static boolean containHTML(String value) {
        return value.indexOf("<") >= 0 || value.indexOf(">") >= 0
                || value.indexOf("&") >= 0 || value.indexOf("\"") >= 0
                || value.indexOf("'") >= 0 || value.indexOf("\\") >= 0;
    }

    public static boolean contains(String array[], String value) {
        for (int i = 0; array != null && i < array.length; i++)
            if (array[i].equals(value))
                return true;

        return false;
    }

    public static boolean isEmail(String email) {
        if (isNull(email))
            return false;
        if (!allValidChars(email))
            return false;
        if (email.indexOf("@") < 1)
            return false;
        if (email.lastIndexOf(".") <= email.indexOf("@"))
            return false;
        if (email.indexOf("@") == email.length())
            return false;
        if (email.indexOf("..") >= 0)
            return false;
        return email.indexOf(".") != email.length();
    }

    public static boolean isMobile(String mobile) {
        if (isNull(mobile))
            return false;
        return Pattern
                .matches(
                        "^(13[0-9]|14[5|6|7|8|9]|15[0|1|2|3|5|6|7|8|9]|16[6|7]|17[0|1|2|3|4|5|6|7|8]|18[0-9]|19[1|8|9])\\d{8}$",
                        mobile);
    }

    /**
     * Created on 2015年2月10日
     * <p>Description:验证身份证</p>
     *
     * @param idNumber
     * @return
     * @author:崔海英
     */
    public static boolean isIdNumber(String idNumber) {
        if (isNull(idNumber))
            return false;
        //String reg = "^(\\d{15}$|^\\d{18}$|^\\d{17}(\\d|X|x))$";
        // String reg = "^[1-9]\\d{5}(18|19|([23]\\d))\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$";
        String reg = "(^[1-9]\\d{5}(18|19|([23]\\d))\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$)|(^[1-9]\\d{5}\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{2}[0-9Xx]$)";
        if (Pattern.matches(reg, idNumber)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 是否是汉字
     *
     * @param character
     * @return
     * @see [类、类#方法、类#成员]
     */
    public static boolean isChineseCharacter(String character) {
        if (isNull(character))
            return false;
        String reg = "^[\u4e00-\u9fa5]+$";
        if (Pattern.matches(reg, character)) {
            return true;
        } else {
            return false;
        }
    }


    /**
     * 由字母、数字、汉字、括号（半角或全角）组成
     *
     * @param character
     * @author zhaoyunfeng
     * @date 2018/11/7
     */
    public static boolean isNumberOrCharacterOrLetter(String character) {
        if (isNull(character)) {
            return false;
        }
        String str = "^[a-zA-Z0-9\u4e00-\u9fa5()（）]+$";

        if (Pattern.matches(str, character)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 由字母、数字、汉字、括号（半角或全角）以及连字符-组成
     *
     * @param character 字符串
     * @author zhaoXinXing
     * @date 2019/4/1
     */
    public static boolean isNumberOrCharacterOrLetterOrHyphen(String character) {
        if (isNull(character)) {
            return false;
        }
        String str = "^[a-zA-Z0-9\u4e00-\u9fa5()（）-]+$";
        return Pattern.matches(str, character);
    }

    /**
     * 由字母、数字、汉字、括号（半角或全角）以及连字符-组成
     *
     * @param character 字符串
     * @author zhaoXinXing
     * @date 2019/4/1
     */
    public static boolean isNumberOrLetterOrHyphen(String character) {
        if (isNull(character)) {
            return false;
        }
        String str = "^[0-9\u4e00-\u9fa5()（）-]+$";
        return Pattern.matches(str, character);
    }


    /**
     * 由汉字、括号（半角或全角）组成
     *
     * @param character
     * @author xuzhengdong
     */
    public static boolean isChineseCharacterOrBracket(String character) {
        if (isNull(character)) {
            return false;
        }
        String str = "^[\u4e00-\u9fa5()（）]+$";

        if (Pattern.matches(str, character)) {
            return true;
        } else {
            return false;
        }
    }

    public static boolean allValidChars(String c) {
        c = c.toLowerCase();
        boolean parsed = true;
        String validchars = "abcdefghijklmnopqrstuvwxyz0123456789@.-_";
        for (int i = 0; i < c.length(); i++) {
            char letter = c.charAt(i);
            if (validchars.indexOf(letter) != -1)
                continue;
            parsed = false;
            break;
        }

        return parsed;
    }

    public static String NullToDoubleQuotes(String str) {
        if (isNull(str))
            return "";
        return str;
    }

    /**
     * 检测是否有emoji字符
     *
     * @param source
     * @return 一旦含有就抛出
     */
    public static boolean isEmoji(String source) {
        if (StringUtils.isBlank(source)) {
            return false;
        }

        int len = source.length();

        for (int i = 0; i < len; i++) {
            char codePoint = source.charAt(i);

            if (isEmoji(codePoint)) {
                // do nothing，判断到了这里表明，确认有表情字符
                return true;
            }
        }

        return false;
    }

    public static boolean isEmoji(char codePoint) {
        return (codePoint == 0x0) || (codePoint == 0x9) || (codePoint == 0xA)
                || (codePoint == 0xD)
                || ((codePoint >= 0x20) && (codePoint <= 0xD7FF))
                || ((codePoint >= 0xE000) && (codePoint <= 0xFFFD))
                || ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF));
    }

    public static boolean equals(String s1, String s2) {
        if (s1 == null && s2 == null) {
            return true;
        } else if (s1 == null && s2 != null) {
            return s2.equals(s1);
        } else if (s1 != null && s2 == null) {
            return s1.equals(s2);
        } else {
            return s1.equals(s2);
        }
    }

    /**
     * 校验字符串中是否包含solr非法字符
     *
     * @param s
     * @return
     * @see [类、类#方法、类#成员]
     */
    public static boolean isSolrIllegalChar(String s) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c == '\\' || c == '+' || c == '-' || c == '!' || c == '(' || c == ')' || c == ':'
                    || c == '^' || c == '[' || c == ']' || c == '\"' || c == '{' || c == '}' || c == '~'
                    || c == '*' || c == '?' || c == '|' || c == '&' || c == ';' || c == '/'
                    || Character.isWhitespace(c)) {
                sb.append('\\');
            }
            sb.append(c);
        }
        return !sb.toString().equals(s);
    }

    /**
     * 是否是数字
     *
     * @return
     * @see [类、类#方法、类#成员]
     */
    public static boolean isNumber(String number) {
        if (isNull(number))
            return false;
        String reg = "^[0-9]*$";
        if (Pattern.matches(reg, number)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 验证是否是整数或小数
     * @param args
     * @return
     */
    public static boolean isIntOrDecimal(String args){
        String regex = "^\\d*((\\.[0-9]*)?)$";
        if (isNull(args)){
            return false;
        }
        if (args.matches(regex)){
            return true;
        }else {
            return false;
        }
    }

    /**
     * 国内固定电话验证
     *
     * @param fixedPhone
     * @return
     */
    public static boolean isFixedPhone(String fixedPhone) {
        if (isNull(fixedPhone))
            return false;
        String reg = "^0\\d{2,3}-\\d{7,8}$";
        return Pattern.matches(reg, fixedPhone);
    }

    /**
     * 判断图片地址是否正确
     *
     * @param url
     * @return
     */
    public static boolean isPicUrl(String url) {
        if (isNull(url)) {
            return false;
        }
        if (url instanceof String) {
            Pattern pattern = Pattern.compile("(http|ftp|https)://([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)+\\.(png|jpg|gif)");
            Matcher matcher = pattern.matcher(url);
            return matcher.matches();
        } else {
            return false;
        }

    }

    /**
     * 判断是否是自然数
     *
     * @param number
     * @return
     */
    public static boolean isNaturalNumber(String number) {
        if (isNull(number)) {
            return false;
        }
        return Pattern.matches("[0-9]\\d*\\.?\\d*", number);
    }

    /**
     * 是否是正常字符
     *
     * @param name
     * @return
     */
    public static boolean isNormalCharacters(String name) {
        Pattern p = Pattern.compile("[^`~!@#$^&*()+=|{}':;',\\[\\].<>/?~！@#￥……&*（）——|{}【】‘；：”“'。，、？%]+");
        Matcher m = p.matcher(name);
        return m.matches();
    }


    /**
     * 验证用户名 6~20位字母+数字，字母开头
     *
     * @param account
     * @return
     */
    public static boolean isAccount(final String account) {
        String regex = "^[a-zA-Z][a-zA-Z0-9_]{5,19}$";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(account);
        return matcher.find();
    }

    /**
     * 验证用户别名 验证规则 min：2 max：15 允许出现 汉字 字母 (可以大小写) 数字 下划线(—)
     *
     * @return true 不含有非法字符 false 含有非法字符
     * @author zhuzb1
     */
    public boolean validateCharacters(final String str) {
        boolean returnVal = false;
        String regex = "^([\\u4e00-\\u9fa5]|[a-z]|[A-Z]|[0-9]|_){2,15}$";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(str);
        returnVal = matcher.find();
        return returnVal;
    }

    /**
     * 将String时间格式转成DateTime类型
     *
     * @param arg
     * @author 马广周
     * @date 2018/12/27 17:32
     */
    public static DateTime stringToDateTime(String arg) {
        Locale locale;
        DateTime ret;
        locale = Locale.ENGLISH;
        if (arg == null || "".equals(arg))
            return null;
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", locale);
            ret = new DateTime(sdf.parse(arg).getTime());
            return ret;
        } catch (ParseException e) {

        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm", locale);
            ret = new DateTime(sdf.parse(arg).getTime());
            return ret;
        } catch (ParseException e1) {

        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", locale);
            ret = new DateTime(sdf.parse(arg).getTime());
            return ret;
        } catch (ParseException e2) {

        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM", locale);
            ret = new DateTime(sdf.parse(arg).getTime());
            return ret;
        } catch (ParseException e3) {

        }

        try {
            SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", locale);
            return new DateTime(sdf.parse(arg).getTime());
        } catch (Exception e4) {

        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy.M", locale);
            ret = new DateTime(sdf.parse(arg).getTime());
            return ret;
        } catch (ParseException e5) {

        }
        throw new IllegalArgumentException("参数非法:" + arg);
    }

}